#pragma once
#include "../domain/Graph.h"
#include "../domain/List.h"
#include "../domain/Vertex.h"
#include "../domain/Edge.h"
#include "../domain/IntNode.h"
#include "../domain/MapObject.h"
#include "../domain/MapObjectNode.h"

const float INF = -1.00000;
const int WEIGHT_COL = 0;
const int VERTEX_ID_COL = 1;

class GraphManager
{
private:
	Graph* graph;
	Edge* phantomEdge;

	/**
	 * Returns if there's a node which is not checked
	 */
	bool notAllChecked(bool* checked, int size);
	/**
	 * Gets the vertex with the min distance loaded in the distance array
	 * See Dijkstra documentation for further specifications.
	 */
	Vertex* getMinimalDistanceVertex(const Graph& graph, bool* checked,  float (*distance)[2], int size);


	/**
	 * Creates the routing table for a vertex
	 */
	List* createRoutingTable(float (*distance)[2], Vertex* targetVertex, List* shortestPastIndexes);

	/**
	 * Initializes distances array
	 */
	void initializeDistances(float (*distance)[2], int n);
	/**
	 * Initialize checks array. Holds information if a node is checked in current dijkstra run.
	 */
	void initializeChecks (bool* checked, int n);

	int getIndexOfVertex(const List& vertexList ,const Vertex& vertex);
public:
	GraphManager(Graph* graph);
	virtual ~GraphManager(void);

	List* getShortestPath(string vertexFrom, string vertexTo);

	List* getFastestPath(string vertexFrom, string vertexTo);

	List* getShortestPathFromEdges(string edgeIdFrom, string edgeIdTo);

	List* getFastestPathFromEdges(string edgeIdFrom, string edgeIdTo);

	/**
	 * Runs algorithm to load the best path from any vertex to another
	 */
	List* runDijkstra(string vertexFrom, string vertexTo);

	Graph* getGraph() const;

	void setGraph(Graph* graph);

	Edge* getPhantomEdge() const;

	void setPhantomEdge(Edge* phantomEdge);
	
	/**
	* Validate the addres, if the addres exist returns the id of the edge that contains the addres
	*/
	string validateAddres(string path, int number);

	void addPhantomEdge(Edge* edge);

	void removePhantomEdge();

	float calculateTotalTime(List* vertexListPath, int mode);

	List* getFastestPathFromEdgeToBuilding(string edgeIdFrom, int from, List* mapObjects, MapObject &near);

	List* getClosestPathFromEdgeToBuilding(string edgeIdFrom, int from, List* mapObjects, MapObject &near);

	Edge* getEgdeForBuildingPath(Edge* originalEdge, int number);

};
